﻿//Copyright (c) 2009, Offbeat Guides
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are 
//permitted provided that the following conditions are met:
//
//* Redistributions of source code must retain the above copyright notice, this list of 
//conditions and the following disclaimer.
//
//* Redistributions in binary form must reproduce the above copyright notice, this list 
//of conditions and the following disclaimer in the documentation and/or other materials 
//provided with the distribution.
//
//* Neither the name of Offbeat Guides nor the names of its contributors may be used to 
//endorse or promote products derived from this software without specific prior written 
//permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
//EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
//OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
//SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
//OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
//TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
//EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Xml;

namespace Amazon.Services.S3
{
    public static class Directory
    {
        #region Static Methods
        public static DirectoryInfo CreateDirectory(AmazonAccount account, String fullpath)
        {
            Match match = FileSystemHelper.PathRegex.Match(fullpath);
            if (!match.Success)
                throw new ArgumentException(String.Format("Unable to locate the directory specified. directory = \"{0}\".", fullpath));

            String bucket = match.Groups["bucket"].Value;
            if (bucket.Length > DriveInfo.MaxNameLength || bucket.Length < DriveInfo.MinNameLength)
                throw new ArgumentException("Drive length is beyond the accepted length.");

            String path = FileSystemHelper.NormalizePath(match.Groups["path"].Value);
            if (!String.IsNullOrEmpty(path) && (path.Length > DirectoryInfo.MaxPathLength || path.Length < DirectoryInfo.MinPathLength))
                throw new ArgumentException("Path length is beyond the accepted length.");

            ServiceClient client = new ServiceClient(account, S3Configuration.Default);
            if (FileSystemHelper.FileExists(client,bucket,FileSystemHelper.ToDirectory(path)))
                throw new IOException("Directory already exists and cannot be overwritten.");

            FileSystemHelper.CreateFile(client, bucket, FileSystemHelper.ToDirectory(path));
            return new DirectoryInfo(client, bucket, path);
        }

        public static void Delete(AmazonAccount account, String fullpath)
        {
            Directory.Delete(account, fullpath, false);
        }

        public static void Delete(AmazonAccount account, String fullpath, Boolean recursive)
        {
            if (account == null)
                throw new ArgumentNullException("account");
            if (String.IsNullOrEmpty(fullpath))
                throw new ArgumentNullException("fullpath");

            Match match = FileSystemHelper.PathRegex.Match(fullpath);
            if (!match.Success)
                throw new ArgumentException(String.Format("Unable to locate the directory specified. directory = \"{0}\".", fullpath));

            String bucket = match.Groups["bucket"].Value;
            if (bucket.Length > DriveInfo.MaxNameLength || bucket.Length < DriveInfo.MinNameLength)
                throw new ArgumentException("Drive length is beyond the accepted length.");

            String path = FileSystemHelper.NormalizePath(match.Groups["path"].Value);
            if (!String.IsNullOrEmpty(path) && (path.Length > DirectoryInfo.MaxPathLength || path.Length < DirectoryInfo.MinPathLength))
                throw new ArgumentException("Path length is beyond the accepted length.");

            FileSystemHelper.DeleteDirectory(new ServiceClient(account, S3Configuration.Default), bucket, path + "/", recursive);
        }

        public static Boolean Exists(AmazonAccount account, String fullpath)
        {
            if (account == null)
                throw new ArgumentNullException("account");
            if (String.IsNullOrEmpty(fullpath))
                throw new ArgumentNullException("fullpath");

            Match match = FileSystemHelper.PathRegex.Match(fullpath);
            if (!match.Success)
                throw new ArgumentException(String.Format("Unable to locate the directory specified. directory = \"{0}\".", fullpath));

            String bucket = match.Groups["bucket"].Value;
            if (bucket.Length > DriveInfo.MaxNameLength || bucket.Length < DriveInfo.MinNameLength)
                throw new ArgumentException("Drive length is beyond the accepted length.");

            String path = FileSystemHelper.NormalizePath(match.Groups["path"].Value);
            if (!String.IsNullOrEmpty(path) && (path.Length > DirectoryInfo.MaxPathLength || path.Length < DirectoryInfo.MinPathLength))
                throw new ArgumentException("Path length is beyond the accepted length.");

            return FileSystemHelper.FileExists(new ServiceClient(account, S3Configuration.Default), bucket, FileSystemHelper.ToDirectory(path));
        }

        public static String[] GetDirectories(AmazonAccount account, String fullpath)
        {
            if (account == null)
                throw new ArgumentNullException("account");
            if (String.IsNullOrEmpty(fullpath))
                throw new ArgumentNullException("fullpath");

            Match match = FileSystemHelper.PathRegex.Match(fullpath);
            if (!match.Success)
                throw new ArgumentException(String.Format("Unable to locate the directory specified. directory = \"{0}\".", fullpath));

            String bucket = match.Groups["bucket"].Value;
            if (bucket.Length > DriveInfo.MaxNameLength || bucket.Length < DriveInfo.MinNameLength)
                throw new ArgumentException("Drive length is beyond the accepted length.");

            String path = FileSystemHelper.NormalizePath(match.Groups["path"].Value);
            if (!String.IsNullOrEmpty(path) && (path.Length > DirectoryInfo.MaxPathLength || path.Length < DirectoryInfo.MinPathLength))
                throw new ArgumentException("Path length is beyond the accepted length.");

            String metadataPath = FileSystemHelper.ToDirectory(path);
            List<String> dirPaths = new List<String>();
            String[] objectPaths = FileSystemHelper.GetObjectPaths(new ServiceClient(account, S3Configuration.Default), bucket, path, false, true, false);
            for (int i = 0; i < objectPaths.Length; i++)
            {
                if (!objectPaths[i].Equals(metadataPath, StringComparison.OrdinalIgnoreCase))
                {
                    String dirPath = String.Format("{0}:\\{1}", bucket, objectPaths[i].Replace(FileSystemHelper.MetadataFilename, String.Empty).Trim('/').Replace('/','\\'));
                    dirPaths.Add(dirPath);
                }
            }
            return dirPaths.ToArray();
        }

        public static String[] GetFiles(AmazonAccount account, String fullpath)
        {
            if (account == null)
                throw new ArgumentNullException("account");
            if (String.IsNullOrEmpty(fullpath))
                throw new ArgumentNullException("fullpath");

            Match match = FileSystemHelper.PathRegex.Match(fullpath);
            if (!match.Success)
                throw new ArgumentException(String.Format("Unable to locate the directory specified. directory = \"{0}\".", fullpath));

            String bucket = match.Groups["bucket"].Value;
            if (bucket.Length > DriveInfo.MaxNameLength || bucket.Length < DriveInfo.MinNameLength)
                throw new ArgumentException("Drive length is beyond the accepted length.");

            String path = FileSystemHelper.NormalizePath(match.Groups["path"].Value);
            if (!String.IsNullOrEmpty(path) && (path.Length > DirectoryInfo.MaxPathLength || path.Length < DirectoryInfo.MinPathLength))
                throw new ArgumentException("Path length is beyond the accepted length.");

            List<String> filePaths = new List<String>();
            String[] objectPaths = FileSystemHelper.GetObjectPaths(new ServiceClient(account, S3Configuration.Default), bucket, path, true, false, false);
            for (int i = 0; i < objectPaths.Length; i++)
            {
                String filePath = objectPaths[i].Substring(path.Length, objectPaths[i].Length - path.Length);
                filePaths.Add(filePath);
            }
            return filePaths.ToArray();
        }
        #endregion
    }
}
